package cn.changein.framework.util.beantools;


import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

/**

 * @Date: 2020/6/10 10:51
 */
public class Copier {
    private static Cache<Key, Copy> copierCache = CacheBuilder.newBuilder().maximumSize(1024L).build();

    public Copier() {
    }

    public static <F, T> T copy(final F from, final T to, final String ignoreProperties) {
        Copy copier = getCopy(from, to);
        copier.copy(from, to, ignoreProperties);
        return to;
    }

    public static <F, T> T copy(final F from, final T to) {
        return copy(from, to, (String) null);
    }

    public static <F, T> T merge(final F from, final T to, final String ignoreProperties) {
        Copy copier = getCopy(from, to);
        copier.merge(from, to, ignoreProperties);
        return to;
    }

    public static <F, T> T merge(final F from, final T to) {
        return merge(from, to, (String) null);
    }

    private static <F, T> Copy getCopy(final F from, final T to) {
        try {
            Key key = getKey(from, to);
            Copy copier = (Copy) copierCache.get(key, new Callable<Copy>() {
                @Override
                public Copy call() throws Exception {
                    Generator gen = new Generator();
                    gen.setSource(from.getClass());
                    gen.setTarget(to.getClass());
                    return (Copy) gen.generate().newInstance();
                }
            });
            return copier;
        } catch (ExecutionException var4) {
            throw new RuntimeException(var4);
        }
    }

    private static Key getKey(Object from, Object to) {
        Class<?> fromClass = from.getClass();
        Class<?> toClass = to.getClass();
        return new Key(fromClass, toClass);
    }
}
